package util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.Element;

import bean.Item;

/**
 * Handles a DOM
 * 
 * @author issuser
 * 
 */
public class DOMUtil {
	/**
	 * org.w3c.dom.Document -> org.dom4j.Document
	 * 
	 * @param doc
	 *            Document(org.w3c.dom.Document)
	 * @return Document
	 */
	public static Document parse(org.w3c.dom.Document doc) throws Exception {
		if (doc == null) {
			return (null);
		}
		org.dom4j.io.DOMReader xmlReader = new org.dom4j.io.DOMReader();
		return (xmlReader.read(doc));
	}

	/**
	 * org.dom4j.Document -> org.w3c.dom.Document
	 * 
	 * @param doc
	 *            Document(org.dom4j.Document)
	 * @throws Exception
	 * @return Document
	 */
	public static org.w3c.dom.Document parse(Document doc) throws Exception {
		if (doc == null) {
			return (null);
		}
		java.io.StringReader reader = new java.io.StringReader(doc.asXML());
		org.xml.sax.InputSource source = new org.xml.sax.InputSource(reader);
		javax.xml.parsers.DocumentBuilderFactory documentBuilderFactory = javax.xml.parsers.DocumentBuilderFactory
				.newInstance();
		javax.xml.parsers.DocumentBuilder documentBuilder = documentBuilderFactory
				.newDocumentBuilder();
		return (documentBuilder.parse(source));
	}

	/**
	 * Transform all the sub-elements under a specified one to HashMap
	 * 
	 * @param element
	 * @return
	 */
	public static HashMap<String, Object> toHashMap(Element element) {

		HashMap<String, Object> hm = new HashMap<String, Object>();
		// Get all the 1 level sub-nodes under the element
		for (Iterator<?> it = element.elementIterator(); it.hasNext();) {
			Element e = (Element) it.next();
			if (null != e.getName() && null != e.getText()) {
				// Transform the DOM to a HashMap.
				hm.put(e.getName(), e.getText());
			}
		}
		return hm;
	}

	/**
	 * Get all Elements under a certain node
	 */
	public static ArrayList<Item> toItemList(Document doc) {
		// Get the root element
		Element root = doc.getRootElement();
		ArrayList<Item> ali = new ArrayList<Item>(0);
		// Put root as the first element of the arraylist
		Item item = new Item();
		item.setName(root.getName());
		item.setValue(root.getText());
		item.setParentItem(null);
		ali.add(item);

		// Add other elements
		getElements(ali, root, item);
		return ali;
	}

	/**
	 * Get all Elements under a certain node
	 */
	public static ArrayList<Item> getElements(ArrayList<Item> ali,
			Element element, Item parentItem) {
		// Get the sub-nodes under the specific node
		for (Iterator<?> it = element.elementIterator(); it.hasNext();) {
			Element e = (Element) it.next();

			// Transfer an element into an item.
			Item item = new Item();
			item.setName(e.getName());
			item.setValue(e.getText());
			item.setParentItem(parentItem);

			// If the item value starts as '\n', deems it as a node
			if (null != item.getValue() && "" != item.getValue())
				if (item.getValue().length() > 0
						&& '\n' != item.getValue().charAt(0))
					item.setNodeType("leaf");
				else
					item.setNodeType("node");

			ali.add(item);
			ali = getElements(ali, e, item);
		}
		return ali;
	}

	/**
	 * Print a DOM onto screen.
	 * 
	 * @param document
	 * @throws Exception
	 */
	public static void printDOM(Document document) throws Exception {
		ArrayList<Item> ali = DOMUtil.toItemList(document);
		ItemUtil.printItems(ali, ali.get(0));
	}
}
